package ar.edu.caece.pl.asem.model.impl.treeelements;

import ar.edu.caece.pl.asem.model.impl.SymbolTable;
import ar.edu.caece.pl.asem.temp.TemporalGenerator;
import ar.edu.caece.pl.asin.manager.impl.ErrorManager;

public class Procedimiento extends MetodoGenerico {

	public Procedimiento(String name) {
		this.name = name;
		this.setReturnType(SymbolTable.VOID);
		this.label = "PROCEDIMIENTO";
	}

	@Override
	public String toString() {
		return this.getLabel() + ": " + this.getName() + "()";
	}

	@Override
	public void generateASMCode() {
		StringBuffer sb = new StringBuffer();
		if (ErrorManager.debugEnabled) sb.append(TAB + "; Proc-Init" + ENTER);
		
		// Guardo el Metodo actual, para luego guardar el ambiente en la pila
		TemporalGenerator.getInstance().checkPointActualMethod(this);
		
		/*
		 * this.getChildren().get(0) = Parametros
		 * this.getChildren().get(1) = Declaraciones
		 * this.getChildren().get(2) = ReturnType
		 * this.getChildren().get(3) = Cuerpo
		 * 
		 */
		
		String procedureName = this.getName();
		sb.append(procedureName + " proc near" + ENTER);
		
		// <PARAMETROS>
		if (!this.getName().equals("main")) {
			
			// <PARAMETROS>
			// Se tiene que hacer un push porque es el retorno de la funcion, despues vienen los parametros!!!
			sb.append(TAB + "push bp" + ENTER);
			sb.append(TAB + "mov bp, sp" + ENTER);
			
			// Reservar espacio en memoria para variables locales si las tiene!
			if(this.getChildren().get(1).getChildren().size()>0){
				int spaceForLocalVariables = this.getChildren().get(1).getChildren().size() * 2;
				sb.append(TAB + "sub sp, " + spaceForLocalVariables + ENTER);
			}
			
			if (this.getChildren().get(0).getChildren().size() > 0) {
				for (int j = this.getChildren().get(0).getChildren().size() - 1; j >= 0; j--) {
					AbstractElement parameter = this.getChildren().get(0).getChildren().get(j);
					parameter.parent = this;
				}
			}
		}else{
			for(AbstractElement parameter : this.getChildren().get(0).getChildren()){
				parameter.parent = this;
			}
		}
		
		this.code = sb.toString();
		if (ErrorManager.debugEnabled) sb.append(TAB + "; Proc-End?" + ENTER);
		super.generateASMCode();
	}

}
